package com.example.mybluetooth.adapter;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.RequiresApi;

import com.example.mybluetooth.ToastUtils;

import java.util.ArrayList;

import static com.example.mybluetooth.BluetoothUtils.bytesToHexString;

public class BleConnectionHelper {
    public Context mContext;
    public String macAddress;
    //    定义保存服务列表的list
    private static ArrayList<BluetoothGattService> mGattServiceList = new ArrayList<>();
    //蓝牙适配器
    private BluetoothAdapter mBluetoothAdapter;
    //    蓝牙设备
    private BluetoothDevice mBluetoothDevice;
    //    蓝牙管理器
    private BluetoothManager mBluetoothManager;
    //   标记是否连接，默认不连接
    private boolean isConnected = false;
    //标记重置次数
    private int retryCount=0;
    //蓝牙Gatt回调
    private MyBluetoothGattCallback mGattCallback;
    //蓝牙Gatt
    private BluetoothGatt mBluetoothGatt;
    //工作子线程Handler
    private Handler mHandler;
    //主线程回调Handler
    private Handler mMainHandler;
    //特征值展示的布局
    private TextView mCharacteristicValueView;
    //描述值展示的布局
    private TextView mDescriptorValueView;
    //回调监听
    private BleConnectionListener mListener;

    //在构造函数中执行初始化部分代码
    public BleConnectionHelper(Context mContext, String macAddress) {
        this.mContext = mContext.getApplicationContext();
        this.macAddress = macAddress;
        HandlerThread handlerThread = new HandlerThread("BleConnection");
        handlerThread.start();
        //初始化工作线程Handler
        mHandler = new Handler(handlerThread.getLooper());
        //初始化主线程Handler
        mMainHandler = new Handler(mContext.getMainLooper());
        initBluetooth();
    }

    public boolean isConnected() {
        return isConnected;
    }

    public void setConnected(boolean connected) {
        isConnected = connected;
    }



    /**
     * 初始化蓝牙
     */
    private void initBluetooth() {
        //初始化ble设配器
        mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        mGattCallback = new MyBluetoothGattCallback();
    }

    /**
     * 连接
     */
    public void connection() {
        if (!isConnected) {
            //获取原始蓝牙设备对象进行连接
            mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
            //重置连接重试次数
            retryCount = 0;
            //连接设备
            mHandler.post(() -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
                    mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false,
                            mGattCallback, BluetoothDevice.TRANSPORT_LE);
                else mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false, mGattCallback);
            });
        }
    }

    /**
     * 发现服务
     */
    public void discoverServices(){
        if (isConnected){
            mHandler.post(() -> {
                //发现服务
                mBluetoothGatt.discoverServices();
            });
        }
    }

    /**
     * 读取特征
     */
    public void readCharacteristic(BluetoothGattCharacteristic characteristic,TextView characteristicValueView){
        if (isConnected) {
            mHandler.post(() -> {
                mCharacteristicValueView = characteristicValueView;
                mBluetoothGatt.readCharacteristic(characteristic);
            });
        }
    }

    /**
     * 写入特征
     */
    public void writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] byteArray) {
        //在客户端发送前设置写入不响应，可以直接得到写入返回，但还是会触发服务端的onCharacteristicWriteRequest
        //characteristic.writeType = WRITE_TYPE_NO_RESPONSE
        //在发送之前，先设置特征通知.
        //mBluetoothGatt.setCharacteristicNotification(characteristic, true)
        //官网上还有一个将该特征下的描述设置为 通知数值 的步骤，有些硬件需要有些不需要，看具体情况
        /*val descriptor = characteristic.getDescriptor(UUID.fromString(NotificationDescriptorUUID))
           /*val descriptor = characteristic.getDescriptor(UUID.fromString(NotificationDescriptorUUID))
        descriptor.let {
            descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
            mBluetoothGatt.writeDescriptor(descriptor)
        }
        //发送十六进制字符串的字节给连接的ble设备，也不一定是规定16进制的，只要对面能解析得出来。
         */
        characteristic.setValue(byteArray);
        mBluetoothGatt.writeCharacteristic(characteristic);

    }

    /**
     * 设置特征通知
     */
    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic){
        mBluetoothGatt.setCharacteristicNotification(characteristic, true);
    }
    /**
     * 读取描述符
     */
    public void readDescriptor(BluetoothGattDescriptor descriptor,TextView descriptorValueView){
        if (isConnected) {
            mHandler.post(() -> {
                mDescriptorValueView = descriptorValueView;
                mBluetoothGatt.readDescriptor(descriptor);
            });
        }
    }

    /**
     * 写入描述符
     */
    public void writeDescriptor(BluetoothGattDescriptor descriptor,byte[] byteArray){
        descriptor.setValue(byteArray);
        mBluetoothGatt.writeDescriptor(descriptor);
    }

//    注销连接服务
    public void onDestroy() {
        //清空消息
        mHandler.removeCallbacks(null);
        mMainHandler.removeCallbacks(null);
        mHandler.getLooper().quit();

        if (isConnected){
            //断开连接
            closeConnection();
        }
        //清空服务列表
        mGattServiceList.clear();
    }

    /**
     * 断开连接，会触发onConnectionStateChange回调，在onConnectionStateChange回调中调用mBluetoothGatt.close()
     */
    public void  disConnection(){
        if (isConnected) {
            isConnected = false;
            mBluetoothGatt.disconnect();
        }
    }
    /**
     * 彻底关闭连接，不带onConnectionStateChange回调的
     */
    private void closeConnection() {
        if (isConnected) {
            isConnected = false;
            mBluetoothGatt.disconnect();
            //调用close()后，连接时传入callback会被置空，无法得到断开连接时onConnectionStateChange（）回调
            mBluetoothGatt.close();
        }
    }

    /**
     * 尝试重连
     */
    private void tryReConnection(){
        retryCount++;
        //之前尝试连接不成功，先关闭之前的连接
        closeConnection();
        //延迟500ms再重新尝试连接
        mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //获取原始蓝牙设备对象进行连接
                        mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
                        //连接设备
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                    mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false,
                                            mGattCallback, BluetoothDevice.TRANSPORT_LE);
                                } else {
                                    mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false, mGattCallback);
                                }
                            }
                        });
                    }
                }, 500L);
    }

    /**
     * 处理连接状态改变
     */
    public void connectionStateChange(int status, int newState) {
        //断开连接或者连接成功时status = GATT_SUCCESS
        switch (status) {
            case BluetoothGatt.GATT_SUCCESS: {
                //连接成功状态
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    isConnected = true;
                    //连接成功回调
                    mMainHandler.post(new Runnable() {
                                          @Override
                                          public void run() {
                                              if (mListener != null) {
                                                  mListener.onConnectionSuccess();
                                              }
                                          }
                                      }
                    );
                    //发现服务
                    mHandler.postDelayed(new Runnable() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
                        @Override
                        public void run() {
                            mBluetoothGatt.discoverServices();
                        }
                    }, 500L);

                } else {
                    if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                        isConnected = false;
                        //断开连接回调
                        mMainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                if (mListener != null) {
                                    mListener.disConnection();
                                }
                            }
                        });
                        //断开连接状态
                        mBluetoothGatt.close();
                    }

                }
                break;
            }
            default:
                //遇到特殊情况尝试重连，增加连接成功率
                if (retryCount < 1 && !isConnected) {
                    //尝试重连
                    tryReConnection();
                } else {
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //判断是否连接上
                            if (isConnected) {
                                //异常连接断开
                                if (mListener != null) {
                                    mListener.disConnection();
                                }
                            } else {
                                //连接失败回调
                                if (mListener != null) {
                                    mListener.onConnectionFail();
                                }
                            }
                        }
                    });
                    //断开连接
                    closeConnection();
                }
        }
    }
    /**
     * 处理发现服务
     */
    private void servicesDiscovered(int status) {

        switch (status){
            case BluetoothGatt.GATT_SUCCESS:{
                //清空之前的Service列表
                mGattServiceList.clear();
                //重新设置Service列表
                mGattServiceList.addAll(mBluetoothGatt.getServices());
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //发现服务回调
                        if(mListener != null){
                            mListener.discoveredServices();
                        }
                    }
                });
                break;
            }
            default:{
                //发现服务失败
                ToastUtils.showBottomToast(mContext,"发现服务失败");
            }
        }
    }
    /**
     * 特征读取
     */
    private void characteristicRead(int status, BluetoothGattCharacteristic characteristic) {
        switch (status) {
            case BluetoothGatt.GATT_SUCCESS: {
                if (characteristic != null) {
                    final StringBuilder stringBuilder = new StringBuilder();
                    final String value = bytesToHexString(characteristic.getValue());
                    stringBuilder.append("特征读取 CharacteristicUUID = " + characteristic.getUuid().toString());
                    stringBuilder.append(" ,特征值 = " + value);
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //读取特征值回调
                            if (mListener != null) {
                                mListener.readCharacteristic(stringBuilder.toString());
                            }
                            //设置并显示特征值
                            if (mCharacteristicValueView != null) {
                                mCharacteristicValueView.setVisibility(View.VISIBLE);
                                if (value != null && !value.equals("")) {
                                    mCharacteristicValueView.setText("Value:(0x)" + value);
                                } else {
                                    mCharacteristicValueView.setText("value:");
                                }
                            }
                            //置空
                            mCharacteristicValueView = null;
                        }
                    });

                }
                break;
            }
            case BluetoothGatt.GATT_READ_NOT_PERMITTED: {
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //读取特征值回调
                        if (mListener != null) {
                            mListener.readCharacteristic("无读取权限");
                        }
                    }
                });
                //置空
                mCharacteristicValueView = null;
                break;
            }
            default: {
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //读取特征值回调
                        if (mListener != null) {
                            mListener.readCharacteristic("特征读取失败 status = " + status);
                        }
                    }
                });
                //置空
                mCharacteristicValueView = null;
            }
        }
    }

    /**
     * 特征写入
     */
    private void characteristicWrite(int status, BluetoothGattCharacteristic characteristic) {

        switch (status) {
            case BluetoothGatt.GATT_SUCCESS: {
                if (characteristic != null) {
                    final StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("特征写入 CharacteristicUUID = " + characteristic.getUuid().toString());
                    stringBuilder.append(" ,写入值 = " + bytesToHexString(characteristic.getValue()));
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //写特征值回调
                            if (mListener != null) {
                                mListener.writeCharacteristic(stringBuilder.toString());
                            }
                        }
                    });
                }
                break;
            }
            default: {
                //特征写入失败
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //写特征值回调
                        if (mListener != null) {
                            mListener.writeCharacteristic("特征写入失败 status = " + status);
                        }
                    }
                });
            }
        }
    }

    /**
     * 特征改变
     */
    private void characteristicChanged(BluetoothGattCharacteristic characteristic) {

        if (characteristic != null) {
            final StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("特征改变 CharacteristicUUID = " + characteristic.getUuid().toString());
            stringBuilder.append(" ,改变值 = " + bytesToHexString(characteristic.getValue()));
            mMainHandler.post(new Runnable() {
                @Override
                public void run() {
                    //读取特征值回调
                    if (mListener != null) {
                        mListener.characteristicChange(stringBuilder.toString());
                    }
                }
            });
        }

    }

    /**
     * 描述符信息写入
     */
    private void descriptorWrite(int status, BluetoothGattDescriptor descriptor) {

        switch (status) {
            case BluetoothGatt.GATT_SUCCESS: {
                if (descriptor != null) {
                    final StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("描述写入 DescriptorUUID = " + descriptor.getUuid().toString());
                    stringBuilder.append(" ,写入值 = " + bytesToHexString(descriptor.getValue()));
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //读取特征值回调
                            if (mListener != null) {
                                mListener.writeDescriptor(stringBuilder.toString());
                            }
                        }
                    });
                }
                break;
            }
            default: {
                //描述写入失败
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //读取特征值回调
                        if (mListener != null) {
                            mListener.writeDescriptor("描述写入失败 status = " + status);
                        }
                    }
                });

            }
        }

    }

    /**
     * 读取描述信息
     */
    private void descriptorRead(int status, BluetoothGattDescriptor descriptor) {
        switch (status) {
            //操作成功
            case BluetoothGatt.GATT_SUCCESS: {
                if (descriptor != null) {
                    final String value = bytesToHexString(descriptor.getValue());
                    final StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("描述读取 DescriptorUUID =" + descriptor.getUuid().toString());
                    stringBuilder.append(" ,描述值 = " + value);
                    mMainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            //读取特征值回调
                            if (mListener != null) {
                                mListener.readDescriptor(stringBuilder.toString());
                            }
                            //设置并显示描述值
                            if (mDescriptorValueView != null) {
                                mDescriptorValueView.setVisibility(View.VISIBLE);
                                if (value != null && !value.equals("")) {
                                    mDescriptorValueView.setText("Value:(0x)" + value);
                                } else {
                                    mDescriptorValueView.setText("Value:");
                                }
                            }
                            //置空
                            mDescriptorValueView = null;
                        }
                    });
                }
                break;
            }
            //无可读权限//无可读权限
            case BluetoothGatt.GATT_READ_NOT_PERMITTED: {
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //读取特征值回调
                        if (mListener != null) {
                            mListener.readDescriptor("无读取权限");
                        }
                    }
                });
                //置空
                mDescriptorValueView = null;
                break;
            }
            default: {
                mMainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //读取特征值回调
                        if (mListener != null) {
                            mListener.readDescriptor("读取描述失败 status = " + status);
                        }
                    }
                });
                //置空
                mDescriptorValueView = null;
            }
        }
    }

    public static ArrayList<BluetoothGattService> getMGattServiceList() {
        return mGattServiceList;
    }

    public void setBleConnectionListener(BleConnectionListener listener) {
        mListener = listener;
    }



    /**
     * 内部Gatt回调类
     */
    class MyBluetoothGattCallback extends BluetoothGattCallback {
        //连接状态改变回调
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            //抛给工作线程处理，尽快返回
            mHandler.post(new Runnable() {
                              @Override
                              public void run() {
                                  connectionStateChange(status, newState);
                              }
                          });
        }

        //服务发现回调
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //抛给工作线程处理
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    servicesDiscovered(status);
                }
            });
        }

        //特征读取回调
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    characteristicRead(status,characteristic);
                }
            });
        }

        //特征写入回调
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            //抛给工作线程处理
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    characteristicWrite(status,characteristic);
                }
            });
        }
        //特征改变回调（主要由外设回调）
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    characteristicChanged(characteristic);
                }
            });
        }
        //描述写入回调
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            //抛给工作线程处理
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    descriptorWrite(status,descriptor);
                }
            });
        }
        //描述读取回调
        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
            //抛给工作线程处理
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    descriptorRead(status,descriptor);
                }
            });
        }
    }

    /**
     * 监听回调
     */
    public interface BleConnectionListener{
        //连接成功
        public void onConnectionSuccess();
        //连接失败
        public void onConnectionFail();
        //断开连接
        public void disConnection();
        //发现服务
        public void discoveredServices();
        //读取特征值
        public void readCharacteristic(String data);
        //写入特征值
        public void writeCharacteristic(String data);
        //读取描述
        public void readDescriptor(String data);
        //写入描述
        public void writeDescriptor(String data);
        //写入特征值
        public void characteristicChange(String data);
    }

}

